import Foundation


func printTable(_ data:[[String]]){
    for row in data {
        //创建空字符创
        var out = "|"
        
        //把这一行的每一项都拼接到字符串上
        for item in row {
            out += "\(item) |"
        }
        //完成打印出来
        print(out)
    }
    print("\n")
}

let data = [
    ["Joe","38","6"],
    ["Karen","40","18"],
    ["Fred","50","20"],
]


printTable(data)


//给列添加标签
func printTable(_ data:[[String]],withColumnLabels columnLabels:String...){
    //创建包含列头的第一行
    var firstRow = "|"
    
    //记录每一列的宽度
    var columnWidths = [Int]()
    
    for columnLabel in columnLabels {
        let columnHeader = " \(columnLabel) |"
        firstRow += columnHeader
        columnWidths.append(columnLabel.count)
    }
    print(firstRow)
    
    for row in data {
        //创建空字符创
        var out = "|"

        for (index,item) in row.enumerated() {
            let paddingNeeded = columnWidths[index] - item.count
            let padding = repeatElement(" ", count: paddingNeeded).joined(separator: "")
            out += " \(padding)\(item) |"
        }
        
        //完成打印出来
        print(out)
    }
    print("\n")
}


printTable(data,withColumnLabels:"Employee Name","Age","Years of Experience")


//使用模型对象来表示需要打印的数据
struct Person{
    let name:String
    let age:Int
    let yearsOfExperience:Int
}

//类型可以符合多个协议,用 , 隔开即可
struct Department:TabularDataSource{
    var description: String{
        return "Department (\(name))"
    }
    
    var numberOfRows: Int {
        return people.count
    }
    
    var numberOfColums: Int{
        return 3
    }
    
    func label(forColumn column: Int) -> String {
        switch column {
        case 0: return "Employee Name"
        case 1: return "Age"
        case 2: return "Years of Experience"
        default:fatalError("Invalid column!")
        }
    }
    
    func itemFor(row: Int, column: Int) -> String {
        let person = people[row]
        
        switch column {
        case 0: return person.name
        case 1: return String(person.age)
        case 2: return String(person.yearsOfExperience)
        default:fatalError("Invalid column!")
        }
    }
    
    let name:String
    var people:[Person] = []
    
    init(name:String){
        self.name = name
    }
    
    mutating func add(_ person:Person){
        people.append(person)
    }
}

//协议:定义类型需要满足的接口,满足某个协议的类型被称为符合这个协议
//协议的继承,协议可以继承一个父协议
//符合这个协议的类型必须实现这个协议以及父协议的必须属性和方法
protocol TabularDataSource:CustomStringConvertible {
    var numberOfRows:Int{get}
    var numberOfColums:Int{get}
    
    func label(forColumn column:Int) -> String
    func itemFor(row:Int, column:Int) -> String
    
}

//让printTable(_:)接受TabularDataSource
func printTable(_ dataSource:TabularDataSource){
    print("Table: \(dataSource.description)")
    //创建包含列头的第一行
    var firstRow = "|"
    
    //记录每一列的宽度
    var columnWidths = [Int]()
    
    for i in 0 ..< dataSource.numberOfColums {
        let columnLabel = dataSource.label(forColumn: i)
        let columnHeader = " \(columnLabel) |"
        firstRow += columnHeader
        columnWidths.append(columnLabel.count)
    }
    print(firstRow)
    
    for i in 0 ..< dataSource.numberOfRows {
        //创建空字符创
        var out = "|"
        
        //把每一行的每一项都拼接到字符串上
        for j in 0 ..< dataSource.numberOfColums {
            let item = dataSource.itemFor(row: i, column: j)
            var paddingNeeded = columnWidths[j] - item.count
            if paddingNeeded < 0{
                paddingNeeded = 0
            }
            let padding = repeatElement(" ", count: paddingNeeded).joined(separator: "")
            out += " \(padding)\(item) |"
        }
        print(out)
    }
    print("\n")
}


var department = Department(name: "Engineering")
department.add(Person(name: "Joe", age: 3000, yearsOfExperience: 6))
department.add(Person(name: "Karen", age: 40, yearsOfExperience: 18))
department.add(Person(name: "Fred", age: 50, yearsOfExperience: 20))

printTable(department)
